from enum import Enum
from command import Command
from abc import abstractmethod

__all__ = [
    "CeilingFan", "CeilingFanHighCommand", "CeilingFanMediumCommand",
    "CeilingFanLowCommand", "CeilingFanOffCommand"
]

class CeilingFan:
    class Speed(Enum):
        HIGH = 3
        MEDIUM = 2
        LOW = 1
        OFF = 0

    def __init__(self, location: str):
        self._location = location
        self._speed = self.Speed.OFF

    def high(self):
        self._speed = self.Speed.HIGH
        print(f"{self._location} ceiling fan is on high")

    def medium(self):
        self._speed = self.Speed.MEDIUM
        print(f"{self._location} ceiling fan is on medium")

    def low(self):
        self._speed = self.Speed.LOW
        print(f"{self._location} ceiling fan is low")

    def off(self):
        self._speed = self.Speed.OFF
        print(f"{self._location} ceiling fan is off")

    @property
    def speed(self):
        return self._speed


class CeilingFanCommand(Command):
    def __init__(self, ceiling_fan: CeilingFan):
        self._ceiling_fan = ceiling_fan
        self._state_history = []

    @abstractmethod
    def execute(self):
        ...

    def undo(self):
        if self._state_history:
            match self._state_history.pop():
                case CeilingFan.Speed.HIGH:
                    self._ceiling_fan.high()
                case CeilingFan.Speed.MEDIUM:
                    self._ceiling_fan.medium()
                case CeilingFan.Speed.LOW:
                    self._ceiling_fan.low()
                case CeilingFan.Speed.OFF:
                    self._ceiling_fan.off()
                case _:
                    pass


class CeilingFanHighCommand(CeilingFanCommand):
    def execute(self):
        self._state_history.append(self._ceiling_fan.speed)
        self._ceiling_fan.high()


class CeilingFanLowCommand(CeilingFanCommand):
    def execute(self):
        self._state_history.append(self._ceiling_fan.speed)
        self._ceiling_fan.low()


class CeilingFanMediumCommand(CeilingFanCommand):
    def execute(self):
        self._state_history.append(self._ceiling_fan.speed)
        self._ceiling_fan.medium()


class CeilingFanOffCommand(CeilingFanCommand):
    def execute(self):
        self._state_history.append(self._ceiling_fan.speed)
        self._ceiling_fan.off()